package com.bianmaba.spring.security.database.access.intercept;

import com.bianmaba.spring.security.basic.configuration.BasicWebSecurityConfigurerAdapter;
import com.bianmaba.spring.security.database.access.DatabaseAccessDecisionManager;
import com.bianmaba.spring.security.database.configuration.DatabaseWebSecurityConfigurerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.Order;
import org.springframework.security.access.SecurityMetadataSource;
import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
import org.springframework.security.access.intercept.InterceptorStatusToken;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.servlet.*;
import java.io.IOException;

import static com.bianmaba.spring.security.autoconfig.WebSecurityAutoConfiguration.ORDER;


@Service
@ConditionalOnClass({WebSecurityConfigurerAdapter.class})
//如果此类加载前已经存在指定类型的实例，则此类将不会被实例化(如果有继承关系，则可能会执行构造函数，但实际为同一个实例时为正常，否则可能不正常)
@ConditionalOnMissingBean({DatabaseSecurityFilter.class})
@Order(ORDER)//配置初始化排序，此值越低，越靠前，但@Import引入的类此注解无效
@Import({DatabaseSecurityMetadataSource.class, DatabaseAccessDecisionManager.class})
public class DatabaseSecurityFilter extends FilterSecurityInterceptor {

    @Autowired
    private DatabaseAccessDecisionManager accessDecisionManager;
    @Autowired
    private DatabaseSecurityMetadataSource securityMetadataSource;
    private static final Logger LOG = LoggerFactory.getLogger(DatabaseSecurityFilter.class);

    public DatabaseSecurityFilter() {
        if (this.getClass().getName().equals(DatabaseSecurityFilter.class.getName())) ;
        {
            LOG.info("加载安全性配置过滤器(order=" + (ORDER - 1) + "):" + DatabaseSecurityFilter.class.getName());
        }
    }


    @PostConstruct
    public void init() {
        super.setAccessDecisionManager(accessDecisionManager);
        super.setSecurityMetadataSource(securityMetadataSource);
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        FilterInvocation fileInvocation = new FilterInvocation(request, response, chain);
        invoke(fileInvocation);
    }

    public void invoke(FilterInvocation fi) throws IOException, ServletException {
        InterceptorStatusToken token = super.beforeInvocation(fi);

        try {
            fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
        } finally {
            super.finallyInvocation(token);
        }
        super.afterInvocation(token, (Object) null);
    }
}
